package org.jftstool.search.client;


import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.data.BasePagingLoader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.extjs.gxt.ui.client.data.PagingLoader;
import com.extjs.gxt.ui.client.data.PagingModelMemoryProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.KeyListener;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.TreePanelEvent;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.util.Padding;
import com.extjs.gxt.ui.client.widget.BoxComponent;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Viewport;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.button.ButtonBar;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.AnchorData;
import com.extjs.gxt.ui.client.widget.layout.AnchorLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayout;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayout;
import com.extjs.gxt.ui.client.widget.layout.BoxLayout.BoxLayoutPack;
import com.extjs.gxt.ui.client.widget.layout.HBoxLayout.HBoxLayoutAlign;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayout.VBoxLayoutAlign;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;


/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class JFTSSearch implements EntryPoint  {
	private ContentPanel panel;
	private ContentPanel lcwest;
	private ContentPanel lceast;	
	private ContentPanel lccenter;
	private ContentPanel lccenterCenter;
	//private LayoutContainer container;
	private TextField<String> inputSearch;
	private ComboBox<TipoConsulta> comboTipoConsulta;
	private SimpleComboBox<String> comboFields;	
	private SimpleComboBox<String> comboLanguages;	
	private JFTSServiceAsync ontoService = GWT.create(JFTSService.class);
	
	

	public void onModuleLoad() {
		Viewport viewport = new Viewport();
		viewport.setLayout(new AnchorLayout());
	
		panel = new ContentPanel();
		lcwest = new ContentPanel();   
		lccenter = new ContentPanel();
		ContentPanel lccenterTOP = new ContentPanel();
		lccenterCenter = new ContentPanel();
		
	    panel.setHeaderVisible(false);   
	    //panel.setSize(800,600);
	    panel.setLayout(new BorderLayout());
	    
	    
	    lcwest = new ContentPanel();   
	    lcwest.setHeaderVisible(true);
	    lcwest.setHeading("Ontolog&iacute;a");	    
	    VBoxLayout westLayout = new VBoxLayout();   
	    westLayout.setPadding(new Padding(5));   
	    westLayout.setVBoxLayoutAlign(VBoxLayoutAlign.STRETCH);
	    lcwest.setLayout(westLayout);
	    
	    lceast = new ContentPanel();   
	    lceast.setHeaderVisible(true);
	    lceast.setHeading("Otros");	    
	    VBoxLayout eastLayout = new VBoxLayout();   
	    eastLayout.setPadding(new Padding(5));   
	    eastLayout.setVBoxLayoutAlign(VBoxLayoutAlign.STRETCH);
	    lceast.setLayout(eastLayout);	    
	    
	    
    
	    lccenter = new ContentPanel();
	    lccenter.setHeaderVisible(true);
	    lccenter.setLayout(new BorderLayout());

	    lccenterTOP = new ContentPanel();
	    lccenterTOP.setHeaderVisible(false);
	    
	    HBoxLayout centerLayout = new HBoxLayout();
	    centerLayout.setPadding(new Padding(5));
	    centerLayout.setHBoxLayoutAlign(HBoxLayoutAlign.MIDDLE);
	    centerLayout.setPack(BoxLayoutPack.CENTER);	    
	    lccenterTOP.setLayout(centerLayout);
	    
	    inputSearch = new TextField<String>();	
	    inputSearch.setWidth(400);
	    lccenterTOP.add(inputSearch);
	    
	    Button buttonSearch = new Button();
	    buttonSearch.setText("Buscar");
	    lccenterTOP.add(buttonSearch);
	    
	    

	    inputSearch.addKeyListener(new KeyListener(){
	    	@Override 
	    	public void componentKeyPress(ComponentEvent event) {
	    		 if (event.getKeyCode() == KeyCodes.KEY_ENTER){
	    			 executeQuery();				
	    		 }
	    	  }	        
	    });

	    
	    buttonSearch.addListener(Events.OnClick, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				executeQuery();				
			}

	    });
	    
	    

	    BorderLayoutData centerNorth = new BorderLayoutData(LayoutRegion.NORTH, 100, 50, 150);   
	    centerNorth.setMargins(new Margins(5));   
	    lccenter.add(lccenterTOP, centerNorth);
	    
	    lccenterCenter = new ContentPanel();
	    lccenterCenter.setHeaderVisible(true);
	    lccenterCenter.setHeading("RESULTADOS");
	    lccenterCenter.setLayout(new AnchorLayout());
	    
	    BorderLayoutData centerCenter = new BorderLayoutData(LayoutRegion.CENTER);   
	    centerCenter.setMargins(new Margins(5));   
	    lccenter.add(lccenterCenter, centerCenter);	    
	    
	    BorderLayoutData west = new BorderLayoutData(LayoutRegion.WEST, 250, 200, 350);   
	    west.setCollapsible(true);
	    west.setFloatable(true);
	    west.setSplit(true);
	    west.setMargins(new Margins(5));
	    
	    BorderLayoutData east = new BorderLayoutData(LayoutRegion.EAST, 250, 200, 350);
	    east.setCollapsible(true);
	    east.setFloatable(true);
	    east.setSplit(true);
	    east.setMargins(new Margins(5));	    
	    
	    BorderLayoutData center = new BorderLayoutData(LayoutRegion.CENTER);   
	    center.setMargins(new Margins(5));   
	    
	    BoxComponent northPanel = new BoxComponent();   
        northPanel.setElement(new HTML("<p align = center>JFTS Tool - Search demo</p>").getElement());   
        panel.add(northPanel, new BorderLayoutData(LayoutRegion.NORTH, 20));
	    
	    
	    panel.add(lccenter, center);   	    
	    panel.add(lcwest, west);
	    panel.add(lceast, east);	    
	    viewport.add(panel, new AnchorData("100% 100%", new Margins(10)));
	    
	    
	    setSearchTable(null);
	    setComboTipoConsulta();
	    setComboFields();
	    setComboLanguages();
	    addOntologyTree(lcwest);	    
	    
	    RootPanel.get().add(viewport);
	}
	    

	private void executeQuery(){
		lccenterCenter.setHeading("RESULTADOS PARA : " + inputSearch.getValue().trim());
		ontoService.executeQuery(inputSearch.getValue().trim(), comboTipoConsulta.getValue().getId(),
				comboLanguages.getSimpleValue(), comboFields.getSimpleValue(), new AsyncCallback<List<ResultadoItem>>() {
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
			}

			public void onSuccess(List<ResultadoItem> result) {
				setSearchTable(result);
			}
		});				
	}
	
	
	private void addOntologyTree(ContentPanel panel){
		ontoService.getOntologyHierarchy(new AsyncCallback<Node>() {
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
			}

			public void onSuccess(Node result) {
				setOntologyTree(result);
			}
		});
	}
	
	public void setOntologyTree(Node result){
		Node model = result;
		//Node model = createModelData();
		TreeStore<ModelData> store = new TreeStore<ModelData>();   
	    store.add(model.getChildren(), true);
	    
	    
	  
	    final TreePanel<ModelData> tree = new TreePanel<ModelData>(store);
	    tree.setDisplayProperty("displayName");   
	    tree.setHeight(690);
	    

	    tree.addListener(Events.OnDoubleClick, new Listener<TreePanelEvent<Node>>() {
			@Override
			public void handleEvent(TreePanelEvent<Node> be) {
				Node n = be.getItem();
				inputSearch.setValue("");
				//lccenterCenter.setHeading("RESULTADOS PARA : " + inputSearch.getValue().trim());
				ontoService.executeQuery(getCategory(n.getCategory()),TipoConsulta.ConsultaPor.PREFIJO,
						"unknown", "category", new AsyncCallback<List<ResultadoItem>>() {
					public void onFailure(Throwable caught) {
						caught.printStackTrace();
					}

					public void onSuccess(List<ResultadoItem> result) {
						setSearchTable(result);
					}
				});								
			}
        });	    
	    
	    ButtonBar buttonBar = new ButtonBar();   
	    
	    buttonBar.add(new Button("Expandir", new SelectionListener<ButtonEvent>() {   
	      public void componentSelected(ButtonEvent ce) {   
	        tree.expandAll();   
	      }   
	    }));   
	    buttonBar.add(new Button("Contraer", new SelectionListener<ButtonEvent>() {   
	      public void componentSelected(ButtonEvent ce) {   
	        tree.collapseAll();   
	      }   
	    }));   
	    lcwest.add(buttonBar);   
	    lcwest.add(tree);
	    lcwest.layout();
	   	    
	}
	
	private String getCategory(String s){
		int i = 0;
		if (s.startsWith("JFTSROOT")){
			i = s.indexOf("/");
		}
		return s.substring(i + 1);
	}
	
	private void setSearchTable(List<ResultadoItem> result){
   
	    PagingModelMemoryProxy proxy = new PagingModelMemoryProxy(result);   
	    PagingLoader<PagingLoadResult<ModelData>> loader = new BasePagingLoader<PagingLoadResult<ModelData>>(proxy);   
	    loader.setRemoteSort(true);
	    
	    ListStore<ResultadoItem> store = new ListStore<ResultadoItem>(loader);   
	    final PagingToolBar toolBar = new PagingToolBar(30);   
	    toolBar.bind(loader);   
	  
	    loader.load(0, 30);
	    
	    List<ColumnConfig> configs = new ArrayList<ColumnConfig>();   
	    
	    ColumnConfig column = new ColumnConfig();   
	    column.setId("id");   
	    column.setHeader("URI");   
	    column.setWidth(300);   
	    configs.add(column);   
	  
	    column = new ColumnConfig();   
	    column.setId("category");   
	    column.setHeader("Categor&iacute;a");   
	    column.setWidth(100);   
	    configs.add(column);   
	    
	    ColumnModel cm = new ColumnModel(configs);
	    
	    ContentPanel cp = new ContentPanel();   
	    //cp.setFrame(true);   
	    //cp.setButtonAlign(HorizontalAlignment.CENTER);   
	    cp.setLayout(new AnchorLayout());	    
	    
  
	    cp.setBottomComponent(toolBar);   
	    cp.setHeaderVisible(false);
	    	  
	    Grid<ResultadoItem> grid = new Grid<ResultadoItem>(store, cm);   
	    grid.setBorders(true);
	    grid.setAutoExpandColumn("id");
	    cp.add(grid, new AnchorData("100% 100%", new Margins(0)));
	    cp.layout();
	    
	    lccenterCenter.removeAll();
	    lccenterCenter.add(cp, new AnchorData("100% 100%", new Margins(0)));
	    lccenterCenter.layout();
    
	}
	
	private void setComboTipoConsulta(){
		ListStore<TipoConsulta> datos = new ListStore<TipoConsulta>();
	    datos.add(TipoConsulta.getDatos());
	    comboTipoConsulta = new ComboBox<TipoConsulta>();	    
	    comboTipoConsulta.setDisplayField("descripcion");
	    comboTipoConsulta.setStore(datos);   
	    comboTipoConsulta.setTypeAhead(true);	
	    comboTipoConsulta.setTriggerAction(TriggerAction.ALL);
	    comboTipoConsulta.setValue(TipoConsulta.getDefault());
		lceast.addText("Tipo de consulta");
		lceast.add(comboTipoConsulta);
		lceast.layout();
	}
	
	private void setComboFields(){
		comboFields = new SimpleComboBox<String>();
		ontoService.getValidFields(new AsyncCallback<List<String>>() {
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
			}

			public void onSuccess(List<String> result) {
				if (result != null && result.size() > 0){
					comboFields = new SimpleComboBox<String>();
					comboFields.add(result);
					comboFields.setSimpleValue(result.get(0));
					lceast.addText("Columna:");
					lceast.add(comboFields);
					lceast.layout();
				}
			}
		});		
	}	
	
	private void setComboLanguages(){
		comboLanguages = new SimpleComboBox<String>();
		ontoService.getValidLanguages(new AsyncCallback<List<String>>() {
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
			}

			public void onSuccess(List<String> result) {
				if (result != null && result.size() > 0){
					comboLanguages = new SimpleComboBox<String>();
					comboLanguages.add(result);
					comboLanguages.setSimpleValue(result.get(0));
					lceast.addText("Idioma:");
					lceast.add(comboLanguages);
					lceast.layout();
				}
			}
		});		
	}	
}